#include "WijiRPC.h"
#include "WijiSettings.h"
#include <QtNetwork>
#include <qhttp.h>
#include "wijiuiscriptable.h"
WijiRPC::WijiRPC()
: QThread(0)
, tcpServer(this), tcpClient(this) {

}
void WijiRPC::init() {
    moveToThread(this);
    start();
}
void WijiRPC::run() {
    qDebug() << "Starting server...";

    connect(
                &tcpServer,
                SIGNAL(newConnection()),
                this,
                SLOT(acceptConnection())
            );
    connect(
                &tcpClient,
                SIGNAL(error(QAbstractSocket::SocketError)),
                this,
                SLOT(displayError(QAbstractSocket::SocketError))
            );
    bytesWritten = 0;
    bytesReceived = 0;

    begin();
    exec();
}
void WijiRPC::begin() {
    WijiSettings* ws = WijiSettings::getSelf();
    while (!tcpServer.isListening() && !tcpServer.listen(QHostAddress::LocalHost, ws->getValue("port").toUInt())) {
        qDebug() << "tcpServer isn't listening...";
    }
    qDebug() << "Finally Listening...";
}
void WijiRPC::acceptConnection()
{
    tcpServerConnection = tcpServer.nextPendingConnection();
    connect(
                tcpServerConnection,
                SIGNAL(readyRead()),
                this,
                SLOT(read())
            );
    connect(
                tcpServerConnection,
                SIGNAL(error(QAbstractSocket::SocketError)),
                this,
                SLOT(displayError(QAbstractSocket::SocketError))
            );

    tcpServer.close();
}
void WijiRPC::read() {
    //Man, this is a mess...oy
    WijiSettings* ws = WijiSettings::getSelf();
    QByteArray buffer = tcpServerConnection->readAll();
    QString json(buffer);
    QHttpRequestHeader header(json);
    QUrl url(header.path());
    qDebug() << "Server received: " + header.path();
    QPair<QString,QString> p;
    QString code;
    QString callback;
    QString name;
    QStringList arguments;
    foreach (p, url.queryItems()) {
        if (url.fromPercentEncoding(p.first.toAscii()).indexOf("method[name") != -1) {
            name = p.second.replace("\"","\\\"");
        }
        if (url.fromPercentEncoding(p.first.toAscii()).indexOf("method[arguments") != -1) {
            arguments << "\"" + url.fromPercentEncoding(p.second.toAscii()).replace("\"","\\\"") + "\"";
        }
        if (url.fromPercentEncoding(p.first.toAscii()).indexOf("callback") != -1) {
            callback = p.second.replace("\"","\\\"");
        }
    }
    code += "var RPC = { callback: \"" +
            callback + "\",\n" +
            "method: {\n" +
            "name: \"" + name + "\",\n" +
            "arguments: [" +
                arguments.join(",") +
            "]\n" +
            "}\n};";
    qDebug() << code;

    char bstr[99];
    //There's gotta be a better way than this...
    sprintf(bstr,"%s/%s.%s",
            ws->getValue("system_scripts").toString().toLatin1().data(),
            "rpc",
            ws->getValue("qt_script_extension").toString().toLatin1().data()
            );
    QString fname =  bstr;
    QFile scriptFile(fname);
    QScriptValue result;
    scriptFile.open(QIODevice::ReadOnly);
    QString contents = scriptFile.readAll();
    WijiUiScriptable *wus = WijiUiScriptable::getSelf();
    QScriptValue wiji = wus->scripter.engine.newQObject(wus, QScriptEngine::ScriptOwnership);
    QScriptValue global = wus->scripter.engine.globalObject();
    if (!global.property(QLatin1String("wiji")).isValid()) {
        global.setProperty(QLatin1String("wiji"), wiji);
    }
    if (!global.property(QLatin1String("_wiji_reserved_output")).isValid()) {
        global.setProperty(QLatin1String("_wiji_reserved_output"), "");
    }
    if (!global.property(QLatin1String("RPC")).isValid()) {
        global.setProperty(QLatin1String("RPC"), "");
    }
    wus->scripter.evalCode(code);
    if (wus->scripter.hasErrors()) {
        qDebug() << "Failed evaluating code.";
        begin();
        return;
    }
    //So the print function works..
    wus->scripter.evalCode("_wiji_reserved_output = ''; print = function (str) { _wiji_reserved_output = _wiji_reserved_output + str;}");
    wus->scripter.evalCode(contents);
    if (wus->scripter.hasErrors()) {
        qDebug() << "Failed evaluating contents.";
        begin();
        return;
    }
    result = wus->scripter.evalCode("_wiji_reserved_output");
    if (wus->scripter.hasErrors()) {
        qDebug() << "Failed evaluating output.";
        begin();
        return;
    }
    begin();
    qDebug() << "Sending Result:" << result.toString();
    sendResult(result.toString());
}
void WijiRPC::processRequest(QVariantMap request) {
    qDebug() << "Got: a request!";
    sendResult(QString("Gotcha!"));
}
void WijiRPC::sendResult(QString result) {
    WijiSettings* ws = WijiSettings::getSelf();
    QTextStream os( tcpServerConnection );

    //os << "HTTP/1.0 200 Ok\r\n" <<
    //        "Content-Type: text/; charset=iso-8859-1\r\n" <<
    //        "Content-Length: " << json.length() << "\r\n" <<
    //        "Connection: close\r\n" <<
    //        "Vary: Accept-Encoding\r\n" <<
    //        "\r\n" <<
    //        json;
    os << result; //send it, rpc.qs is supposed to print out the correct text to send...makes it less of a headache.
    tcpServerConnection->close();
    while (!tcpServer.isListening() && !tcpServer.listen(QHostAddress::LocalHost, ws->getValue("port").toUInt())) {
        qDebug() << "x x tcpServer isn't listening...";
    }
}
void WijiRPC::displayError(QAbstractSocket::SocketError socketError) {

}
